package com.firewolf.strategy;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class MainDriver {

	private SessionFactory factory;

	private Session session;

	private Transaction transaction;
	
	
	@Test
	public void addData(){
		openSession();
		Customer c = new Customer();
		c.setCustomerName("liuxing");
		
		Customer c2 = new Customer();
		c2.setCustomerName("liuxing");
		
		Order o = new Order();
		o.setOrderName("Order-001");
		Order o2 = new Order();
		o2.setOrderName("Order-002");
		Order o3 = new Order();
		o3.setOrderName("Order-003");
		Order oo = new Order();
		oo.setOrderName("Order-00o1");
		Order oo2 = new Order();
		oo2.setOrderName("Order-00o2");
		Order oo3 = new Order();
		oo3.setOrderName("Order-00o3");
		
		Set<Order> orders = new HashSet<>();
		orders.add(o);
		orders.add(o2);
		orders.add(o3);
		Set<Order> orders2 = new HashSet<>();
		orders2.add(oo);
		orders2.add(oo2);
		orders2.add(oo3);
		
		c.setOrders(orders2);
		o.setCustomer(c);
		o2.setCustomer(c);
		o3.setCustomer(c);
		
		c2.setOrders(orders2);
		oo.setCustomer(c2);
		oo2.setCustomer(c2);
		oo3.setCustomer(c2);
		
		session.save(o);
		session.save(o2);
		session.save(o3);
		session.save(c);
		session.save(oo);
		session.save(oo2);
		session.save(oo3);
		session.save(c2);
		
		
		closeSession();
	}
	
	
	/**
	 * 查询一个持久化类，默认是采用懒加载的； 可以通过在配置类的时候使用配置lazy="false"，来立即加载
	 */
	@Test
	public void testClassLevelQueryStategy() {
		openSession();
		Customer customer = (Customer) session.load(Customer.class, 1);
		/** 这个时候没有检索，返回的是代理对象 */
		System.out.println(customer.getClass());
		/** 查询ID，还是没有检索， */
		System.out.println(customer.getCustomerId());
		/** 当需要使用非ID属性的时候，开始检索了 ,这个时候才打印查询语句 */
		System.out.println(customer.getCustomerName());
		closeSession();
	}

	/**
	 * 
	 * set的lazy属性： 1.1-n或者n-n的集合属性默认使用懒加载策略；
	 * 2.可以通过Set的lazy属性来修改检索策略；默认为true，不建议使用false；
	 * 3.lazy还可以设置为extra(增强的延迟检索)，该值为会尽可能的延迟检索实际
	 * 4.可以显示调用Hibernate.initialize方法显示的检索
	 */
	@Test
	public void testOne2ManyQueryStategy() {
		openSession();
		Customer customer = (Customer) session.get(Customer.class, 1);

		System.out.println(customer.getCustomerName());

		// 此时如果设置为extra的话，此时还没有初始化集合，
		System.out.println(customer.getOrders().size());

		/** 可以显示调用Hibernate.initialize方法显示的检索，这个时候会显示的初始化集合 */
		Hibernate.initialize(customer.getOrders());
		closeSession();
	}

	/**
	 * batch-size属性： 一次加载的集合中的数据，有效的较少查询语句，（前提是lazy的值为true才有效果）
	 * 下面的测试中，如果不设置，
	 * 则会有4条查询，因为有4个customer；
	 */
	@Test
	public void testSetBathSize() {
		openSession();
		List<Customer> customers = session.createQuery("From Customer").list();

		for (Customer customer : customers) {
			if (customer != null && customer.getOrders() != null)
				System.out.println(customer.getOrders().size());
		}
		System.out.println(customers.size());
		closeSession();
	}

	/**
	 * set的fetch属性：
	 * 1.默认为select，通过正常的方式来初始化集合；
	 * 2.可以取值为subselect.通过子查询的方式来初始化所有的set集合，
	 * 		子查询作为where子句的in的条件出现，子查询所有的1的一端的ID，
	 *      此时lazy有效，但是bath-size失效，
	 * 
	 */
	@Test
	public void testSetFetch() {
		openSession();
		List<Customer> customers = session.createQuery("From Customer").list();

		for (Customer customer : customers) {
			if (customer != null && customer.getOrders() != null)
				System.out.println(customer.getOrders().size());
		}
		System.out.println(customers.size());
		closeSession();
	}
	
	@Test
	public void testSetFetchJoin() {
		openSession();
		Customer customers = (Customer) session.get(Customer.class, 1);
		System.out.println(customers);
		closeSession();
	}
	
	private void openSession() {
		session = factory.openSession();
		transaction = session.beginTransaction();
	}
	
	private void closeSession() {
		transaction.commit();
		session.close();
	}

	@Before
	public void init() {
		Configuration cfg = new Configuration().configure();

		ServiceRegistry registry = new ServiceRegistryBuilder().applySettings(cfg.getProperties())
				.buildServiceRegistry();
		factory = cfg.buildSessionFactory(registry);
	}

	@After
	public void destory() {
		factory.close();
	}
}
